from flask import Flask, render_template, request, Response
from kubernetes import client, config
from loguru import logger
import requests
import base64
import time

# Flask App
app = Flask(__name__)


class InfoManager():
    def __init__(self):
        self.token = self.__get_token()
        # self.port = self.__get_port()
        self.update_time = time.time()

    def get_token(self) -> str:
        if time.time() - self.update_time < 60:
            return self.token
        else:
            self.token = self.__get_token()
            self.update_time = time.time()
            return self.token

    def get_port(self) -> str:
        if time.time() - self.update_time < 60:
            return self.port
        else:
            self.port = self.__get_port()
            self.update_time = time.time()
            return self.port

    def __get_token(self) -> str:
        config.load_incluster_config()
        cl = client.CoreV1Api()
        ret = cl.read_namespaced_service_account(name='admin-user', namespace='kubernetes-dashboard')
        ret = cl.read_namespaced_secret(name=ret.secrets[0].name, namespace='kubernetes-dashboard')

        logger.info(f"Get Token: {base64.decodebytes(bytes(ret.data['token'], encoding='ascii')).decode(encoding='ascii')}")

        return base64.decodebytes(bytes(ret.data['token'], encoding='ascii')).decode(encoding='ascii')

    def __get_port(self) -> int:
        config.load_incluster_config()
        cl = client.CoreV1Api()
        ret = cl.read_namespaced_service_with_http_info(name='kubernetes-dashboard', namespace='kubernetes-dashboard')

        for port_spec in ret[0].spec.ports:
            if port_spec.port == 443:
                logger.info(f'Nodeport of kubernetes-dashboard: {port_spec.node_port}')
                return port_spec.node_port

        logger.error(f'Service nodeport not found for kubernetes-dashboard:443')
        raise RuntimeError("Service nodeport not found.")


info_manager = InfoManager()


@app.route("/", defaults={"path": ""})
@app.route("/<string:path>")
@app.route("/<path:path>")
def proxy(*args, **kwargs):
    target_url = f'http://kubernetes-dashboard.kubernetes-dashboard:80/'
    target_url = request.url.replace(request.host_url, target_url)
    target_headers = {key: value for (key, value) in request.headers if key != 'Host'}
    target_headers['Authorization'] = 'Bearer ' + info_manager.get_token()

    resp = requests.request(
        method=request.method,
        url=target_url,
        headers=target_headers,
        data=request.get_data(),
        cookies=request.cookies,
        allow_redirects=False,
        verify=False)

    excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
    headers = [(name, value) for (name, value) in resp.raw.headers.items()
               if name.lower() not in excluded_headers]

    response = Response(resp.content, resp.status_code, headers)
    return response


if __name__ == '__main__':
    app.run('0.0.0.0', port=6789, debug=False)
